#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <iconv.h>

#define UTF8_STR "sdd\\xE4\\xB8\\xAD\\xE6\\x96\\x87"
#define GBK_STR "\xB0\xAE\xB5\xCF\xCB\xBCTP-LINK"
static void remove_x_char(char *s){
	int i= 0;
	int j= 0;

	if(strstr(s, "\\x") == NULL){
		printf("no need\n");
		return;
	}

	for(i; s[i] != 0; i++)
	{
		if(s[i] == '\\' && s[i+1] == 'x')
		{
			//skip
			i++;
		}else{
			s[j++] = s[i];
		}
	}	
	s[j] = 0;//end the string
	printf("s [%s]\n",s);
}

bool is_utf8(const char* str)
{
	unsigned int nBytes = 0;//UFT8可用1-6个字节编码,ASCII用一个字节  
	unsigned char chr = *str;
	bool bAllAscii = true;
	unsigned int i = 0;
	for (i = 0; str[i] != '\0'; ++i){
		chr = *(str + i);
		//判断是否ASCII编码,如果不是,说明有可能是UTF8,ASCII用7位编码,最高位标记为0,0xxxxxxx 
		if (nBytes == 0 && (chr & 0x80) != 0){
			bAllAscii = false;
		}
 
		if (nBytes == 0) {
			//如果不是ASCII码,应该是多字节符,计算字节数  
			if (chr >= 0x80) {
 
				if (chr >= 0xFC && chr <= 0xFD){
					nBytes = 6;
				}
				else if (chr >= 0xF8){
					nBytes = 5;
				}
				else if (chr >= 0xF0){
					nBytes = 4;
				}
				else if (chr >= 0xE0){
					nBytes = 3;
				}
				else if (chr >= 0xC0){
					nBytes = 2;
				}
				else{
					return false;
				}
 
				nBytes--;
			}
		}
		else{
			//多字节符的非首字节,应为 10xxxxxx 
			if ((chr & 0xC0) != 0x80){
				return false;
			}
			//减到为零为止
			nBytes--;
		}
	}
 
	//违返UTF8编码规则 
	if (nBytes != 0)  {
		return false;
	}
 
	if (bAllAscii){ //如果全部都是ASCII, 也是UTF8
		return false;
	}
 
	return true;
}

bool is_gbk(char *str){
	unsigned int nBytes = 0;//GBK可用1-2个字节编码,中文两个 ,英文一个 
	unsigned char chr = *str;
	bool bAllAscii = true; //如果全部都是ASCII,  
	unsigned int i = 0;
	for (i = 0; str[i] != '\0'; ++i){
		chr = *(str + i);
		if ((chr & 0x80) != 0 && nBytes == 0){// 判断是否ASCII编码,如果不是,说明有可能是GBK
			bAllAscii = false;
		}

		if (nBytes == 0) {
			if (chr >= 0x80) {
				if (chr >= 0x81 && chr <= 0xFE){
					nBytes = +2;
				}
				else{
					return false;
				}

				nBytes--;
			}
		}
		else{
			if (chr < 0x40 || chr>0xFE){
				return false;
			}
			nBytes--;
		}//else end
	}

	if (nBytes != 0)  {		//违返规则 
		return false;
	}

	if (bAllAscii){ //如果全部都是ASCII, 也是GBK
		return false;
	}

	return true;	
}

static char _char2byte(char hex_ch)
{
    if (hex_ch >= '0' && hex_ch <= '9')
    {
        return hex_ch - '0';
    }

    if (hex_ch >= 'a' && hex_ch <= 'f')
    {
        return hex_ch - 'a' + 10;
    }

    if (hex_ch >= 'A' && hex_ch <= 'F')
    {
        return hex_ch - 'A' + 10;
    }

    return 0x00;
}

/*
* convert string to hex, eg: "1234ABCDEF" -> 1234ABCDEF
*/
static int  _string2hex(char * p_hexstr, char * p_binstr)
{
    int bin_len = 0;
    int hex_len = strlen((char *)p_hexstr);
    int index = 0;

    if (hex_len % 2 == 1)
    {
        hex_len -= 1;
    }

    bin_len = hex_len / 2;

    for(index = 0; index < hex_len; index+=2)
    {
        p_binstr[index/2] = ((_char2byte(p_hexstr[index]) << 4) & 0xF0) + _char2byte(p_hexstr[index + 1]);
    }

    return bin_len;
}

void gbk_to_utf8(const char* src, char* dst, int len)
{
    int ret = 0;
    size_t inlen = strlen(src) + 1;
    size_t outlen = len;

    // duanqn: The iconv function in Linux requires non-const char *
    // So we need to copy the source string
    char* inbuf = (char *)malloc(len);
    char* inbuf_hold = inbuf;   // iconv may change the address of inbuf
                                // so we use another pointer to keep the address
    memcpy(inbuf, src, len);

    char* outbuf2 = NULL;
    char* outbuf = dst;
    iconv_t cd;

    // starkwong: if src==dst, the string will become invalid during conversion since UTF-8 is 3 chars in Chinese but GBK is mostly 2 chars
    if (src == dst) {
        outbuf2 = (char*)malloc(len);
        memset(outbuf2, 0, len);
        outbuf = outbuf2;
    }

    cd = iconv_open("UTF-8", "GBK");
    if (cd != (iconv_t)-1) {
        ret = iconv(cd, &inbuf, &inlen, &outbuf, &outlen);
        if (ret != 0)
            printf("iconv failed err: %s\n", strerror(errno));

        if (outbuf2 != NULL) {
            strcpy(dst, outbuf2);
            free(outbuf2);
        }

        iconv_close(cd);
    }
    free(inbuf_hold);   // Don't pass in inbuf as it may have been modified
}

void convert_chinese_ssid(char *ssid, char *new_ssid){
	int len = strlen(ssid);
		
	int i = 0, j = 0;
	for(i=0; i<len; i++){
		if(ssid[i] == '\\' && ssid[i+1] == 'x'){
			
			//E4->0xe4
			new_ssid[j++] = ((_char2byte(ssid[i+2]) << 4) & 0x000000F0) + _char2byte(ssid[i + 3]);
			//printf("new ssid [%d][%x]\n", j, new_ssid[j-1]);
			i=i+3;
		}else{
			new_ssid[j++] = ssid[i];
		}
	}
	new_ssid[j] = 0;
}

int main(int argc, void *argv[]){

	char new_ssid[64] ={0} ;
	char last_ssid[64] ={0} ;
	convert_chinese_ssid(GBK_STR, new_ssid);
	is_gbk(new_ssid)?printf("gbk\n"):printf("not gbk\n");
	
	if(is_gbk(new_ssid)){
		gbk_to_utf8(new_ssid, last_ssid, sizeof(last_ssid));
		printf("gbk2utf8 [%s]\n",last_ssid);
	}
	
	is_utf8(new_ssid)?printf("utf8\n"):printf("not utf8\n");	
				
	convert_chinese_ssid(UTF8_STR, new_ssid);
	printf("hex [%s]\n",new_ssid);		
	
	
	return;

}
